#include "model/model.h"

#include "smart_serve_log.h"
#include "service/service.h"

namespace OHOS {
namespace SmartServe {

ModelResConfig Model::conservativeResConfig()
{
    if (!pending_) {
        return currentResConfig_;
    }
    return ModelResConfig{.memSize_ = std::max(pendingResConfig_.memSize_, currentResConfig_.memSize_)};
}

bool Model::isRunnable() const
{
    auto& rc = (pending_) ? pendingResConfig_ : currentResConfig_;

    for (auto& cfg : resConfigs_) {
        if (cfg.isSatisfiedBy(rc)) {
            return true;
        }
    }

    return false;
}

void Model::TriggerPending(const ModelResConfig& newResConfig)
{
    SMART_SERVE_LOGD("[Model] TriggerPending");

    ASSERT(!pending_);

    pendingResConfig_ = newResConfig;
    pending_ = true;

    Service::Instance()->maintainer_.AddTask([this]() { HandlePending(); });
}

void Model::HandlePending()
{
    SMART_SERVE_LOGD("[Model] HandlePending");

    ASSERT(pending_);

    ModelApplyResult result = ModelApplyResult::UNCHANGED;
    if (!terminating_) {
        result = adapter_->ApplyResConfig(pendingResConfig_);
    }
    FinishPendingUse(result);
}

void Model::FinishPendingUse(const ModelApplyResult& result)
{
    bool successful = (result == ModelApplyResult::SUCCESSFUL);

    // 生成回复 Event
    auto event = std::make_unique<ModelAppliedEvent>(currentResConfig_, pendingResConfig_, successful);

    // 处理 FATAL
    if (result == ModelApplyResult::FATAL) {
        std::unique_lock<std::mutex> lock(Service::Instance()->msMgmtMutex_);
        TriggerTerminating();
    }

    {
        std::unique_lock<std::mutex> lock(mutex_);

        // 修改 resConfig
        if (successful) {
            currentResConfig_ = pendingResConfig_;
        }

        // 清理 pending_
        pending_ = false;
    }

    // 通知 Scheduler
    Service::Instance()->scheduler_->Schedule(std::move(event));
}

void Model::TriggerTerminating()
{
    SMART_SERVE_LOGD("[Model] TriggerTerminating");

    auto service = Service::Instance();

    // 移除管理结构
    {
        // 移除 Model
        auto self = service->modelManager_.RemoveModel(this).release();

        // 检查是否已被他人终止
        if (self == nullptr) { // 因为维护管理结构由终止发起者完成，为空说明已经被终止过
            ASSERT(terminating_);
            return;
        }

        // 设置 Terminating
        AsyncTerminate();
        ASSERT(self == this);

        // 移除 Session 并唤醒退出
        for (auto session : sessions_) {
            auto pSession = service->sessionManager_.RemoveSession(session).release();
            ASSERT(pSession == session);

            for (auto model : session->models_) {
                if (model != this) {
                    model->RemoveSession(session);
                }
            }

            // 设置 Terminating 并唤醒
            session->AsyncTerminate();
        }
    }

    // 通知 Maintainer 回收
    service->maintainer_.AddTask([this]() {
        auto& scheduler = Service::Instance()->scheduler_;

        // Sessions
        for (auto session : sessions_) {
            session->WaitForTerminated();
            scheduler->Schedule(std::make_unique<SessionReleseEvent>(session));
        }

        // Model (self)
        WaitForTerminated();
        scheduler->Schedule(std::make_unique<ModelReleseEvent>(this));
    });
}

} // namespace SmartServe
} // namespace OHOS